package com.ocean.core.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ocean.core.exception.verify.ApplicationException;
import com.ocean.core.util.constants.ConstantsAttribute;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;

/**
 * 生成二维码
 *
 * @author zhang
 * @since 2023/11/4
 */
public class QRCodeUtil {

    /**
     * 生成二维码
     *
     * @param content 扫码后要调用的链接地址
     * @param width   二维码宽度
     * @param height  二维码高度
     * @return base64
     */
    public static String createQrCode(String content, int width, int height) throws IOException {
        String resultImage = "";
        //除了尺寸，传入内容不能为空
        if (!StringUtils.isEmpty(content)) {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            //二维码参数
            HashMap<EncodeHintType, Object> hints = new HashMap<>();
            //指定字符编码为“utf-8”
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            //L M Q H四个纠错等级从低到高，指定二维码的纠错等级为M
            //纠错级别越高，可以修正的错误就越多，需要的纠错码的数量也变多，相应的二维吗可储存的数据就会减少
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            //设置图片的边距
            hints.put(EncodeHintType.MARGIN, 1);

            try {
                //zxing生成二维码核心类
                QRCodeWriter writer = new QRCodeWriter();
                //把输入文本按照指定规则转成二维吗
                BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
                //生成二维码图片流
                BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
                //输出流
                ImageIO.write(bufferedImage, "png", os);
                //原生转码前面没有 data:image/png;base64 这些字段，返回给前端是无法被解析，所以加上前缀
                resultImage = ("data:image/png;base64," + encodeBase64(os.toByteArray()));
                return resultImage;
            } catch (Exception e) {
                e.printStackTrace();
                //自己编写的异常处理类，也可以使用java自带的异常处理
                throw new ApplicationException(ConstantsAttribute.ERROR);
            }
        }
        return null;
    }

    private static String encodeBase64(byte[] data) {
        return Base64.getEncoder().encodeToString(data);
    }

    public static void main(String[] args) throws IOException {
        String qrCode = createQrCode("http://www.baidu.com", 200, 200);
        System.out.println(qrCode);
    }
}